﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AlipaySDK.Alipay;
using AlipaySDK.Dto.Payment;
using Aop.Api;
using Aop.Api.Request;
using Aop.Api.Response;
using Jayrock.Json;
using static System.String;

namespace AlipaySDK.Helper
{
    public class QrCodePayment
    {
        readonly IAopClient client;

        public QrCodePayment()
        {
            client = new DefaultAopClient(AlipayConfig.serverUrl, AlipayConfig.appId, AlipayConfig.merchant_private_key,
                "", AlipayConfig.version,
                AlipayConfig.sign_type, AlipayConfig.alipay_public_key, AlipayConfig.charset);

        }

        /// <summary>
        /// 创建诊单支付二维码
        /// </summary>
        /// <param name="request"><see cref="ComposeWapPayRequest"/></param>
        /// <returns></returns>
        public CreatePaymentQrCodeResponse CreateQrCodeResult(ComposeWapPayRequest request)
        {
            //var logger = LogManager.GetLogger("CommonLogger");
            //logger.Info(new CustomLog
            //{
            //    Message = "CreateQrCodeResult request:" + Newtonsoft.Json.JsonConvert.SerializeObject(request)
            //});

            string notify_url = request.NotifyUrl;
            string out_trade_no = request.OutTradeNo;
            string subject = request.Subject;
            string total_fee = request.TotalFee;

            //请根据实际请求需要biz_content参数
            var bizContent = new JsonObject();
            //商户订单号
            bizContent.Put("out_trade_no", out_trade_no);
            //支付金额
            bizContent.Put("total_amount", total_fee);
            //折扣金额
            bizContent.Put("discountable_amount", 0.00);
            //订单标题
            bizContent.Put("subject", subject);
            //商户操作员编号自定义
            bizContent.Put("operator_id", "op001");
            //商户店铺号自定义
            bizContent.Put("store_id", "sfy001");
            //商户终端号
            bizContent.Put("terminal_id", "t_001");
            //过期时间，默认15分钟后自动取消支付
            bizContent.Put("time_expire", DateTime.Now.AddMinutes(15).ToString("yyyy-MM-dd HH:mm:ss"));

            //请根据实际请求需要biz_content参数
            //StringBuilder sb = new StringBuilder();
            //sb.Append("{\"out_trade_no\":\"" + out_trade_no + "\",");
            //sb.Append("\"total_amount\":\"" + total_fee + "\",\"discountable_amount\":\"0.00\",");
            //sb.Append("\"subject\":\"" + subject + "\",\"body\":\"test\",");
            ////sb.Append("\"goods_detail\":[{\"goods_id\":\"apple-01\",\"goods_name\":\"ipad\",\"goods_category\":\"7788230\",\"price\":\"5.00\",\"quantity\":\"1\"},{\"goods_id\":\"apple-02\",\"goods_name\":\"iphone\",\"goods_category\":\"7788231\",\"price\":\"2.76\",\"quantity\":\"1\"}],");
            //sb.Append("\"operator_id\":\"op001\",\"store_id\":\"sfy001\",\"terminal_id\":\"t_001\",");

            //string expire_time = System.DateTime.Now.AddMinutes(30).ToString("yyyy-MM-dd HH:mm:ss");
            //sb.Append("\"time_expire\":\"" + expire_time + "\"}");

            AlipayTradePrecreateResponse payResponse = Prepay(client, bizContent.ToString(), notify_url);

            if (payResponse != null)
            {
                if (CompareOrdinal(payResponse.Code, ResultCode.SUCCESS) == 0)
                {
                    return new CreatePaymentQrCodeResponse
                    {
                        ResultCode = "0",
                        ResultMsg = "",
                        CodeImg = payResponse.QrCode,
                        OutTradeNo = out_trade_no
                    };
                }
                //StringBuilder sb2 = new StringBuilder();
                //sb2.Append("{\"out_trade_no\":\"" + out_trade_no + "\"}");
                if (payResponse.SubCode != "ACQ.TRADE_HAS_SUCCESS")
                {
                    var cancelContent = new JsonObject();
                    //商户订单号
                    cancelContent.Put("out_trade_no", out_trade_no);
                    Cancel(cancelContent.ToString());
                }
                return new CreatePaymentQrCodeResponse
                {
                    ResultCode = "1",
                    ResultMsg = payResponse.SubCode + payResponse.SubMsg,
                    CodeImg = "",
                    OutTradeNo = out_trade_no
                };
            }

            return new CreatePaymentQrCodeResponse
            {
                ResultCode = "1",
                ResultMsg = "调用支付宝扫码支付API出错:",
            };


        }



        /// <summary>
        /// 统一下单交易查询
        /// 交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）
        /// 、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）
        /// 、TRADE_SUCCESS（交易支付成功）
        /// 、TRADE_FINISHED（交易结束，不可退款）
        /// </summary>
        /// <param name="request"><see cref="WapPayQueryRequest"/></param>
        /// <returns></returns>
        public WapPayQueryResponse AcquireQuery(WapPayQueryRequest request)
        {
            var queryContent = new JsonObject();
            //商户订单号
            queryContent.Put("out_trade_no", request.OutTradeNo);

            AlipayTradeQueryResponse payResponse = Query(queryContent.ToString());

            string result = payResponse.Body;

            if (CompareOrdinal(payResponse.Code, ResultCode.SUCCESS) == 0)
            {
                return new WapPayQueryResponse()
                {
                    ResultCode = "0",
                    ResultMsg = "成功",
                    IsSuccess = "T",
                    TradeStatu = payResponse.TradeStatus,
                    TradeNo = payResponse.TradeNo
                };
            }
            return new WapPayQueryResponse()
            {
                ResultCode = "1",
                ResultMsg = "失败",
                IsSuccess = "F",
                TradeStatu = payResponse.SubCode + payResponse.SubMsg
            };
        }


        /// <summary>
        /// 支付宝退款
        /// </summary>
        /// <param name="request"><see cref="AcquireRefundRequest"/></param>
        /// <returns></returns>
        public AcquireRefundResponse AcquireRefund(AcquireRefundRequest request)
        {
            var refundContent = new JsonObject();
            refundContent.Put("out_request_no", request.BatchNo);
            refundContent.Put("trade_no", request.TradeNo);
            refundContent.Put("refund_amount", request.RefundAmount);

            //StringBuilder sb = new StringBuilder();
            //sb.Append("{\"out_request_no\":\"" + request.OutTradeNo + "\",");
            //sb.Append("\"trade_no\":\"" + request.TradeNo + "\",");
            //sb.Append("\"refund_amount\":\"" + request.RefundAmount + "\"}");

            AlipayTradeRefundResponse refundResponse = Refund(refundContent.ToString());

            string sHtmlText = refundResponse.Body;

            if (Compare(refundResponse.Code, ResultCode.SUCCESS, false) == 0)
            {
                return new AcquireRefundResponse()
                {
                    ResultCode = "0",
                    ResultMsg = "成功",
                    IsSuccess = "T",
                    TradeNo = refundResponse.TradeNo,
                    GmtRefundPay = refundResponse.GmtRefundPay
                };
            }
            return new AcquireRefundResponse
            {
                ResultCode = "1",
                ResultMsg = refundResponse.SubCode + refundResponse.SubMsg
            };
        }


        /// <summary>
        /// 支付宝单面付，扫码付通知结果验签
        /// </summary>
        /// <param name="request"><see cref="WapPayVerifyNotifyRequest"/></param>
        /// <returns></returns>
        public WapPayVerifyNotifyResponse VerifyAcquireNotify(WapPayVerifyNotifyRequest request)
        {
            AliF2FNotify aliNotify = new AliF2FNotify();
            //string sPara = request.SPara;
            string sign = request.Sign;
            //Dictionary<string, string> inputPara = new Dictionary<string, string>();
            Dictionary<string, string> inputPara = request.SPara;
            try
            {
                //inputPara = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(sPara);
                SortedDictionary<string, string> dicTemp = new SortedDictionary<string, string>(inputPara);
                string notifyId;
                inputPara.TryGetValue("notify_id", out notifyId);
                bool verifyResult = aliNotify.Verify(dicTemp, notifyId, sign);
                if (verifyResult) //验证成功
                {
                    return new WapPayVerifyNotifyResponse
                    {
                        ResultCode = "0",
                        ResultMsg = "成功",
                        //NotifyData = inputPara["notify_data"] ?? inputPara["batch_no"]
                    };
                }
                else
                {
                    return new WapPayVerifyNotifyResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "验签失败"
                    };
                }

            }
            catch (Exception ee)
            {
                return new WapPayVerifyNotifyResponse
                {
                    ResultCode = "1",
                    ResultMsg = ee.Message
                };
            }

        }



        private AlipayTradePrecreateResponse Prepay(IAopClient client, string biz_content, string notifyUrl)
        {
            AlipayTradePrecreateRequest payRequst = new AlipayTradePrecreateRequest();
            payRequst.BizContent = biz_content;

            //需要异步通知的时候，需要是指接收异步通知的地址。
            payRequst.SetNotifyUrl(notifyUrl);

            Dictionary<string, string> paramsDict = (Dictionary<string, string>)payRequst.GetParameters();
            //new DefaultAopClient(Config.serverUrl, Config.appId, Config.merchant_private_key);

            AlipayTradePrecreateResponse payResponse = client.Execute(payRequst);
            return payResponse;
        }


        private AlipayTradeCancelResponse Cancel(string biz_content)
        {
            AlipayTradeCancelRequest cancelRequest = new AlipayTradeCancelRequest();
            cancelRequest.BizContent = biz_content;
            AlipayTradeCancelResponse cancelResponse = client.Execute(cancelRequest);


            if (null != cancelResponse)
            {
                if (cancelResponse.Code == ResultCode.FAIL && cancelResponse.RetryFlag == "Y")
                {
                    //if (cancelResponse.Body.Contains("\"retry_flag\":\"Y\""))		
                    //cancelOrderRetry(biz_content);
                    // 新开一个线程重试撤销
                    ParameterizedThreadStart ParStart = new ParameterizedThreadStart(CancelOrderRetry);
                    Thread myThread = new Thread(ParStart);
                    object o = biz_content;
                    myThread.Start(o);
                }
            }

            return cancelResponse;

        }


        private void CancelOrderRetry(object o)
        {
            int retryCount = 50;

            for (int i = 0; i < retryCount; ++i)
            {

                Thread.Sleep(10000);
                AlipayTradeCancelRequest cancelRequest = new AlipayTradeCancelRequest();
                cancelRequest.BizContent = o.ToString();
                // Dictionary<string, string> paramsDict = (Dictionary<string, string>)cancelRequest.GetParameters();
                AlipayTradeCancelResponse cancelResponse = client.Execute(cancelRequest);

                if (null != cancelResponse)
                {
                    if (cancelResponse.Code == ResultCode.FAIL)
                    {
                        //if (cancelResponse.Body.Contains("\"retry_flag\":\"N\""))		
                        if (cancelResponse.RetryFlag == "N")
                        {
                            break;
                        }
                    }
                    if ((cancelResponse.Code == ResultCode.SUCCESS))
                    {
                        break;
                    }
                }

                if (i == retryCount - 1)
                {
                    // 处理到最后一次，还是未撤销成功，需要在商户数据库中对此单最标记，人工介入处理

                }

            }
        }


        private AlipayTradeQueryResponse LoopQuery(string biz_content)
        {

            AlipayTradeQueryRequest payRequst = new AlipayTradeQueryRequest();
            payRequst.BizContent = biz_content;

            Dictionary<string, string> paramsDict = (Dictionary<string, string>)payRequst.GetParameters();
            AlipayTradeQueryResponse payResponse = null;

            for (int i = 1; i <= 6; i++)
            {
                Thread.Sleep(5000);

                payResponse = client.Execute(payRequst);
                if (Compare(payResponse.Code, ResultCode.SUCCESS, false) == 0)
                {
                    if (payResponse.TradeStatus == "TRADE_FINISHED"
                        || payResponse.TradeStatus == "TRADE_SUCCESS"
                        || payResponse.TradeStatus == "TRADE_CLOSED")
                        break;
                }

            }

            StringBuilder sb1 = new StringBuilder();
            sb1.Append("{\"out_trade_no\":\"" + payResponse.OutTradeNo + "\"}");
            biz_content = sb1.ToString();
            Cancel(biz_content);

            return payResponse;

        }

        private AlipayTradeQueryResponse Query(string biz_content)
        {

            AlipayTradeQueryRequest payRequst = new AlipayTradeQueryRequest();
            payRequst.BizContent = biz_content;

            Dictionary<string, string> paramsDict = (Dictionary<string, string>)payRequst.GetParameters();
            AlipayTradeQueryResponse payResponse = client.Execute(payRequst);

            return payResponse;
        }

        private AlipayTradeRefundResponse Refund(string biz_content)
        {
            AlipayTradeRefundRequest payRequst = new AlipayTradeRefundRequest();
            payRequst.BizContent = biz_content;

            Dictionary<string, string> paramsDict = (Dictionary<string, string>)payRequst.GetParameters();

            AlipayTradeRefundResponse payResponse = client.Execute(payRequst);

            return payResponse;

        }
    }
}
